package CamaddLSBzyx0722;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

public class DrawMouse implements ActionListener,MouseListener {
    public Graphics g;
    private Graphics bg;

    private BufferedImage bufferedImage;
    public String fn;//= "D:\\JAVAproject\\idea\\BeautyCam\\src\\Cam3zyx0711\\flower.jpg";
    public String str;

    public JPanel j1=null;
    public int s=1 ;

    public int a,b;
    public void mouseClicked(MouseEvent e){
        // 先在本地暂存区进行存储 ---> 上传到本地的仓库  ----> 远程仓库
        int x =a= e.getX();
        int y =b= e.getY();
    }
    public void mousePressed(MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}






    public void actionPerformed(ActionEvent e) {
        String btnStr = e.getActionCommand();
        str = btnStr;
        System.out.println("用户点击了" + btnStr+"按钮......");
        System.out.println("稍等一会，图片效果马上呈现");
        // 使用SwingWorker来执行异步图像处理
        SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
            protected Void doInBackground() {
                // 根据按钮选择的效果处理图像
        //根据字符串绘制相关图片
        switch (btnStr) {
            case "原图":
                oripic();
                break;
            case "灰度"://取rgb平均值，则画成灰度图
                grey();
                break;
            case "二值化":
                binarization();
                break;
            case "马赛克":
                mosaic();
                break;
            case"放大":
                Todouble();
                break;
            case"缩小":
                narrow();
                break;
            case"油画":
                oil();
                break;
            case"哈哈镜":
                funhouseMirror();
                break;
            case "旋转":
                spin();
                break;
            case "加密":
                encrypt();
                break;
        }
        return null;
    }
            protected void done() {
                // 图像处理完成后的操作，更新UI等
                g.drawImage(bufferedImage, 0, 22, j1);
            }
        };

        // 执行SwingWorker中的异步图像处理
        worker.execute();
    }

        //程序的执行过程：代码 > jvm > os > 总线 > 显示器
        //创建缓冲区 把所有的像素点显示在缓存去上
        public void bufferZone() {
            int[][] data = image(fn);
            bufferedImage = new BufferedImage( data.length, data[0].length,BufferedImage.TYPE_INT_RGB);
            bg = bufferedImage.getGraphics();
            bg.setColor(Color.WHITE);
            bg.fillRect(0,0,bufferedImage.getWidth(),bufferedImage.getHeight());
    }



       public void oripic(){
           bufferZone();
           int[][] data = image(fn);//图片放在项目目录下
           for (int i = 0; i < data.length; i++) {
                for (int j = 0; j < data[i].length; j++) {
                    //得到颜色值，画出每一个点
                    Color c = new Color(data[i][j]);
                    bg.setColor(c);//g.setColor(new Color(data[i][j])）；
                    bg.fillOval(i / 2, j /2, 2, 2);
                }
            }

            //把缓冲区显示在窗体；
            g.drawImage(bufferedImage,0,22,j1);
        }
    public void grey(){
       bufferZone();
       int[][] data = image(fn);
        for (int i = 0; i < data.length; i++){
            for (int j = 0; j < data[i].length; j++){
                Color color = new Color(data[i][j]);
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int sum = (red+green+blue)/3;
                Color newColor = new Color(sum,sum,sum);
                bg.setColor(newColor);
                bg.drawOval(i/2,j/2,1,1);
            }
        }
        //把缓冲区显示在窗体；
        g.drawImage(bufferedImage,0,22,j1);
    }

    public void mosaic() {
        bufferZone();
        int x = s;
      int[][] data = image(fn);
        for (int i = 0; i < data.length; i += (15+1.6*x)) {
            for (int j = 0; j < data[i].length; j += (15+1.6*x)) {
                Color color = new Color(data[i][j]);
                bg.setColor(color);
                bg.fillRect(i / 2, j/ 2, 15, 15);
            }
        }
        //把缓冲区显示在窗体；
        g.drawImage(bufferedImage,0,22,j1);
    }

    public void binarization() {
        bufferZone();
        int x = s;
        int[][] data = image(fn);
        int h = data.length;
        int w = data[0].length;
        for(int i = 0; i < h; i++){
            for(int j = 0; j < w; j++){
                int p = data[i][j];
                Color color = new Color(p);
                int blue = color.getBlue();
                if (blue >(70+2*x)){
                    bg.setColor(Color.BLACK);
                }else{
                    bg.setColor(Color.WHITE);
                }
                bg.drawOval(i/2,j/2,1,1);
            }
        }
        //把缓冲区显示在窗体；
        g.drawImage(bufferedImage,0,22,j1);
    }

    public void narrow(){
       bufferZone();
       int x = s;
       int[][] data = image(fn);//图片放在项目目录下
        int w= data.length;
        int h=data[0].length;
        for (int i = 0; i < w; i+=2) {
            for (int j = 0; j < h; j+=2) {
                //得到颜色值，画出每一个点
                Color c = new Color(data[i][j]);
                bg.setColor(c);//g.setColor(new Color(data[i][j])）；
                bg.fillRect(i/(2*x) , j/(2*x), x, x);
            }
        }
        g.drawImage(bufferedImage, 0, 22, j1);

    }
    public void Todouble(){
        bufferZone();
        int x = s;
       int[][] data = image(fn);//图片放在项目目录下
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                //得到颜色值，画出每一个点
                Color c = new Color(data[i][j]);
                bg.setColor(c);//g.setColor(new Color(data[i][j])）；
                bg.fillRect(i*(x/2)/2, j *(x/2)/2, x, x);
            }
        }
        g.drawImage(bufferedImage, 0, 22, j1);

    }

    public void oil(){
        bufferZone();
        int x = s;
        int[][] data = image(fn);
        for (int i =0; i < data.length-5; i +=5){
            for (int j =0; j < data[i].length-5; j +=5) {
                Color color = new Color(data[i][j]);
                bg.setColor(color);
                Random ran=new Random();
                int r1 = ran.nextInt(20)*x+5;
                int r2 = ran.nextInt(40)*x+5;
                bg.fillOval((i+x)/2, (j+x)/2,Math.max(r1,r2), Math.min(r1,r2));
            }
        }
        //把缓冲区显示在窗体；
        g.drawImage(bufferedImage,0,22,j1);
    }


    public void funhouseMirror() {
        bufferZone();
        int x = s;
        int[][] data = image(fn);
        int h=data.length;
        int w=data[0].length;
        int maxDist = (int) Math.sqrt((w/2 - a) * (w/2 - a) + (h/2 - b) * (h/2 - b));
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                int deltaX = i - b;
                int deltaY = j - a;
                double distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
                int newX = (int) (i + deltaX * x * maxDist / distance*0.1);
                int newY = (int) (j + deltaY * x * maxDist / distance*0.1);

                if (newX >= 0 && newX < data.length && newY >= 0 && newY < data[i].length) {
                    Color color = new Color(data[newX][newY]);
                    bg.setColor(color);
                    bg.drawOval(i/2, j/2, 1, 1);
                }
            }
        }
        // 把缓冲区显示在窗体；
        g.drawImage(bufferedImage, 0, 22, j1);
    }


    public void encrypt(){
        bufferZone();
        int[][] data = image(fn);
        System.out.println("请输入所要加入图像里的信息:");
        Scanner scanner = new Scanner(System.in);
        String messageToEncrypt = scanner.nextLine();
        scanner.close();
        int messageIndex = 0;

        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                if (messageIndex < messageToEncrypt.length()) {
                    Color color = new Color(data[i][j]);
                    int red = color.getRed();
                    int green = color.getGreen();
                    int blue = color.getBlue();

                    char charToHide = messageToEncrypt.charAt(messageIndex);
                    int asciiValue = (int) charToHide;

                    // 将ASCII码值存储到蓝色通道的最低2位
                    blue = (blue & 0xFC) | ((asciiValue >> 6) & 0x03);
                    Color newColor = new Color(red, green, blue);

                    bg.setColor(newColor);
                    bg.drawOval(i / 2, j / 2, 1, 1);

                    messageIndex++;
                } else {
                    // 如果已经加密完整个信息，则将原图像像素写入缓冲区
                    Color color = new Color(data[i][j]);
                    bg.setColor(color);
                    bg.drawOval(i / 2, j / 2, 1, 1);
                }
            }
        }

        // 把缓冲区显示在窗体；
        g.drawImage(bufferedImage, 0, 22, j1);
        try {
            File outputImageFile = new File("encrypted_image.jpg"); // 新文件的路径
            ImageIO.write(bufferedImage, "jpg", outputImageFile);
            System.out.println("加密后的图像已保存到文件 'encrypted_image.jpg'");
        } catch (IOException e) {
            System.out.println("保存图像文件时出现错误: " + e.getMessage());
        }
    }

    public void spin(){
        bufferZone();
        int x = s;
        int[][] data = image(fn);
        // 设置旋转角度（以弧度表示）
        double angle = Math.PI / 4;
        // 计算旋转后图像的宽度和高度
        int w = data.length;
        int h = data[0].length;
        int newW = (int) Math.abs(w * Math.cos(angle)) + (int) Math.abs(h * Math.sin(angle));
        int newH = (int) Math.abs(w * Math.sin(angle)) + (int) Math.abs(h * Math.cos(angle));
        // 创建新的缓冲区用于存储旋转后的图像
        BufferedImage rotatedImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = rotatedImage.createGraphics();
        // 设置背景颜色为白色
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, newW, newH);
        // 设置旋转中心点
        double centerX = w / 2.0;
        double centerY = h / 2.0;
        // 执行图像旋转操作
        AffineTransform transform = new AffineTransform();
        transform.rotate(angle, centerX, centerY);
        g2d.setTransform(transform);
        g2d.drawImage(bufferedImage, 0, 0, j1);
        // 释放资源
        g2d.dispose();
        // 将旋转后的图像复制回缓冲区
        bufferedImage = rotatedImage;
        // 在画板上显示旋转后的图像
        g.drawImage(bufferedImage, 0, 22, null);
    }


    //将一张图片转化一个int型的二维数组
    private int[][] image(String imageName) {
        File file = new File(fn);
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(file); //从文件到图片对象
        } catch (Exception e) {
            e.printStackTrace();
        }
        int w = bi.getWidth(); //图片的宽
        int h = bi.getHeight(); //图片的高
        int[][] imIndex = new int[w][h];//存像素值的二维数组
        //System.out.println("w=" + w + " h=" + h );
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                imIndex[i][j] = bi.getRGB(i, j); //i,j 位置的 Color 值，每个像素点的 color 存入数组
            }
        }
        return imIndex;
    }


}


